1 /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 * 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 package org.mozilla.javascript; 8 9 /** 10 * The JavaScript Script object. 11 * 12 * Note that the C version of the engine uses XDR as the format used 13 * by freeze and thaw. Since this depends on the internal format of 14 * structures in the C runtime, we cannot duplicate it. 15 * 16 * Since we cannot replace 'this' as a result of the compile method, 17 * will forward requests to execute to the nonnull 'script' field. 18 * 19 * @since 1.3 20 * @author Norris Boyd 21 */ 22 23 class NativeScript extends BaseFunction 24 { 25 static final long serialVersionUID = -6795101161980121700L; 26 27 private static final Object SCRIPT_TAG = "Script"; 28 init(Scriptable scope, boolean sealed)29 static void init(Scriptable scope, boolean sealed) 30 { 31 NativeScript obj = new NativeScript(null); 32 obj.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); 33 } 34 NativeScript(Script script)35 private NativeScript(Script script) 36 { 37 this.script = script; 38 } 39 40 /** 41 * Returns the name of this JavaScript class, "Script". 42 */ 43 @Override getClassName()44 public String getClassName() 45 { 46 return "Script"; 47 } 48 49 @Override call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args)50 public Object call(Context cx, Scriptable scope, Scriptable thisObj, 51 Object[] args) 52 { 53 if (script != null) { 54 return script.exec(cx, scope); 55 } 56 return Undefined.instance; 57 } 58 59 @Override construct(Context cx, Scriptable scope, Object[] args)60 public Scriptable construct(Context cx, Scriptable scope, Object[] args) 61 { 62 throw Context.reportRuntimeError0("msg.script.is.not.constructor"); 63 } 64 65 @Override getLength()66 public int getLength() 67 { 68 return 0; 69 } 70 71 @Override getArity()72 public int getArity() 73 { 74 return 0; 75 } 76 77 @Override decompile(int indent, int flags)78 String decompile(int indent, int flags) 79 { 80 if (script instanceof NativeFunction) { 81 return ((NativeFunction)script).decompile(indent, flags); 82 } 83 return super.decompile(indent, flags); 84 } 85 86 @Override initPrototypeId(int id)87 protected void initPrototypeId(int id) 88 { 89 String s; 90 int arity; 91 switch (id) { 92 case Id_constructor: arity=1; s="constructor"; break; 93 case Id_toString: arity=0; s="toString"; break; 94 case Id_exec: arity=0; s="exec"; break; 95 case Id_compile: arity=1; s="compile"; break; 96 default: throw new IllegalArgumentException(String.valueOf(id)); 97 } 98 initPrototypeMethod(SCRIPT_TAG, id, s, arity); 99 } 100 101 @Override execIdCall(IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args)102 public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, 103 Scriptable thisObj, Object[] args) 104 { 105 if (!f.hasTag(SCRIPT_TAG)) { 106 return super.execIdCall(f, cx, scope, thisObj, args); 107 } 108 int id = f.methodId(); 109 switch (id) { 110 case Id_constructor: { 111 String source = (args.length == 0) 112 ? "" 113 : ScriptRuntime.toString(args[0]); 114 Script script = compile(cx, source); 115 NativeScript nscript = new NativeScript(script); 116 ScriptRuntime.setObjectProtoAndParent(nscript, scope); 117 return nscript; 118 } 119 120 case Id_toString: { 121 NativeScript real = realThis(thisObj, f); 122 Script realScript = real.script; 123 if (realScript == null) { return ""; } 124 return cx.decompileScript(realScript, 0); 125 } 126 127 case Id_exec: { 128 throw Context.reportRuntimeError1( 129 "msg.cant.call.indirect", "exec"); 130 } 131 132 case Id_compile: { 133 NativeScript real = realThis(thisObj, f); 134 String source = ScriptRuntime.toString(args, 0); 135 real.script = compile(cx, source); 136 return real; 137 } 138 } 139 throw new IllegalArgumentException(String.valueOf(id)); 140 } 141 realThis(Scriptable thisObj, IdFunctionObject f)142 private static NativeScript realThis(Scriptable thisObj, IdFunctionObject f) 143 { 144 if (!(thisObj instanceof NativeScript)) 145 throw incompatibleCallError(f); 146 return (NativeScript)thisObj; 147 } 148 compile(Context cx, String source)149 private static Script compile(Context cx, String source) 150 { 151 int[] linep = { 0 }; 152 String filename = Context.getSourcePositionFromStack(linep); 153 if (filename == null) { 154 filename = "<Script object>"; 155 linep[0] = 1; 156 } 157 ErrorReporter reporter; 158 reporter = DefaultErrorReporter.forEval(cx.getErrorReporter()); 159 return cx.compileString(source, null, reporter, filename, 160 linep[0], null); 161 } 162 163 // #string_id_map# 164 165 @Override findPrototypeId(String s)166 protected int findPrototypeId(String s) 167 { 168 int id; 169 // #generated# Last update: 2007-05-09 08:16:01 EDT 170 L0: { id = 0; String X = null; 171 L: switch (s.length()) { 172 case 4: X="exec";id=Id_exec; break L; 173 case 7: X="compile";id=Id_compile; break L; 174 case 8: X="toString";id=Id_toString; break L; 175 case 11: X="constructor";id=Id_constructor; break L; 176 } 177 if (X!=null && X!=s && !X.equals(s)) id = 0; 178 break L0; 179 } 180 // #/generated# 181 return id; 182 } 183 184 private static final int 185 Id_constructor = 1, 186 Id_toString = 2, 187 Id_compile = 3, 188 Id_exec = 4, 189 MAX_PROTOTYPE_ID = 4; 190 191 // #/string_id_map# 192 193 private Script script; 194 } 195 196