1 /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
\r
3 * The contents of this file are subject to the Netscape Public
\r
4 * License Version 1.1 (the "License"); you may not use this file
\r
5 * except in compliance with the License. You may obtain a copy of
\r
6 * the License at http://www.mozilla.org/NPL/
\r
8 * Software distributed under the License is distributed on an "AS
\r
9 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express oqr
\r
10 * implied. See the License for the specific language governing
\r
11 * rights and limitations under the License.
\r
13 * The Original Code is Rhino code, released
\r
16 * The Initial Developer of the Original Code is Netscape
\r
17 * Communications Corporation. Portions created by Netscape are
\r
18 * Copyright (C) 1997-1999 Netscape Communications Corporation. All
\r
26 * Alternatively, the contents of this file may be used under the
\r
27 * terms of the GNU Public License (the "GPL"), in which case the
\r
28 * provisions of the GPL are applicable instead of those above.
\r
29 * If you wish to allow use of your version of this file only
\r
30 * under the terms of the GPL and not to allow others to use your
\r
31 * version of this file under the NPL, indicate your decision by
\r
32 * deleting the provisions above and replace them with the notice
\r
33 * and other provisions required by the GPL. If you do not delete
\r
34 * the provisions above, a recipient may use your version of this
\r
35 * file under either the NPL or the GPL.
\r
38 package org.mozilla.javascript;
\r
40 import java.io.StringReader;
\r
41 import java.io.IOException;
\r
42 import java.lang.reflect.Method;
\r
45 * This class implements the global native object (function and value
\r
48 * See ECMA 15.1.[12].
\r
50 * @author Mike Shaver
\r
53 public class NativeGlobal implements IdFunctionMaster {
\r
55 public static void init(Context cx, Scriptable scope, boolean sealed) {
\r
56 NativeGlobal obj = new NativeGlobal();
\r
57 obj.scopeSlaveFlag = true;
\r
59 for (int id = 1; id <= LAST_SCOPE_FUNCTION_ID; ++id) {
\r
60 String name = getMethodName(id);
\r
61 IdFunction f = new IdFunction(obj, name, id);
\r
62 f.setParentScope(scope);
\r
63 if (sealed) { f.sealObject(); }
\r
64 ScriptableObject.defineProperty(scope, name, f,
\r
65 ScriptableObject.DONTENUM);
\r
68 ScriptableObject.defineProperty(scope, "NaN",
\r
69 ScriptRuntime.NaNobj,
\r
70 ScriptableObject.DONTENUM);
\r
71 ScriptableObject.defineProperty(scope, "Infinity",
\r
72 new Double(Double.POSITIVE_INFINITY),
\r
73 ScriptableObject.DONTENUM);
\r
75 ScriptableObject.defineProperty(scope, "undefined",
\r
77 ScriptableObject.DONTENUM);
\r
80 String[] errorMethods = { "ConversionError",
\r
90 Each error constructor gets its own Error object as a prototype,
\r
91 with the 'name' property set to the name of the error.
\r
93 for (int i = 0; i < errorMethods.length; i++) {
\r
94 String name = errorMethods[i];
\r
95 IdFunction ctor = new IdFunction(obj, name, Id_new_CommonError);
\r
96 ctor.setFunctionType(IdFunction.FUNCTION_AND_CONSTRUCTOR);
\r
97 ctor.setParentScope(scope);
\r
98 ScriptableObject.defineProperty(scope, name, ctor,
\r
99 ScriptableObject.DONTENUM);
\r
101 Scriptable errorProto = ScriptRuntime.newObject
\r
102 (cx, scope, "Error", ScriptRuntime.emptyArgs);
\r
104 errorProto.put("name", errorProto, name);
\r
105 ctor.put("prototype", ctor, errorProto);
\r
108 if (errorProto instanceof ScriptableObject) {
\r
109 ((ScriptableObject)errorProto).sealObject();
\r
115 public Object execMethod(int methodId, IdFunction function, Context cx,
\r
116 Scriptable scope, Scriptable thisObj,
\r
118 throws JavaScriptException
\r
120 if (scopeSlaveFlag) {
\r
121 switch (methodId) {
\r
123 return js_decodeURI(cx, args);
\r
125 case Id_decodeURIComponent:
\r
126 return js_decodeURIComponent(cx, args);
\r
129 return js_encodeURI(cx, args);
\r
131 case Id_encodeURIComponent:
\r
132 return js_encodeURIComponent(cx, args);
\r
135 return js_escape(cx, args);
\r
138 return js_eval(cx, scope, args);
\r
141 return js_isFinite(cx, args);
\r
144 return js_isNaN(cx, args);
\r
146 case Id_parseFloat:
\r
147 return js_parseFloat(cx, args);
\r
150 return js_parseInt(cx, args);
\r
153 return js_unescape(cx, args);
\r
155 case Id_new_CommonError:
\r
156 return new_CommonError(function, cx, scope, args);
\r
159 throw IdFunction.onBadMethodId(this, methodId);
\r
162 public int methodArity(int methodId) {
\r
163 if (scopeSlaveFlag) {
\r
164 switch (methodId) {
\r
165 case Id_decodeURI: return 1;
\r
166 case Id_decodeURIComponent: return 1;
\r
167 case Id_encodeURI: return 1;
\r
168 case Id_encodeURIComponent: return 1;
\r
169 case Id_escape: return 1;
\r
170 case Id_eval: return 1;
\r
171 case Id_isFinite: return 1;
\r
172 case Id_isNaN: return 1;
\r
173 case Id_parseFloat: return 1;
\r
174 case Id_parseInt: return 2;
\r
175 case Id_unescape: return 1;
\r
177 case Id_new_CommonError: return 1;
\r
183 private static String getMethodName(int methodId) {
\r
184 switch (methodId) {
\r
185 case Id_decodeURI: return "decodeURI";
\r
186 case Id_decodeURIComponent: return "decodeURIComponent";
\r
187 case Id_encodeURI: return "encodeURI";
\r
188 case Id_encodeURIComponent: return "encodeURIComponent";
\r
189 case Id_escape: return "escape";
\r
190 case Id_eval: return "eval";
\r
191 case Id_isFinite: return "isFinite";
\r
192 case Id_isNaN: return "isNaN";
\r
193 case Id_parseFloat: return "parseFloat";
\r
194 case Id_parseInt: return "parseInt";
\r
195 case Id_unescape: return "unescape";
\r
201 * The global method parseInt, as per ECMA-262 15.1.2.2.
\r
203 private Object js_parseInt(Context cx, Object[] args) {
\r
204 String s = ScriptRuntime.toString(args, 0);
\r
205 int radix = ScriptRuntime.toInt32(args, 1);
\r
207 int len = s.length();
\r
209 return ScriptRuntime.NaNobj;
\r
211 boolean negative = false;
\r
215 c = s.charAt(start);
\r
216 if (!Character.isWhitespace(c))
\r
219 } while (start < len);
\r
221 if (c == '+' || (negative = (c == '-')))
\r
224 final int NO_RADIX = -1;
\r
227 } else if (radix < 2 || radix > 36) {
\r
228 return ScriptRuntime.NaNobj;
\r
229 } else if (radix == 16 && len - start > 1 && s.charAt(start) == '0') {
\r
230 c = s.charAt(start+1);
\r
231 if (c == 'x' || c == 'X')
\r
235 if (radix == NO_RADIX) {
\r
237 if (len - start > 1 && s.charAt(start) == '0') {
\r
238 c = s.charAt(start+1);
\r
239 if (c == 'x' || c == 'X') {
\r
242 } else if (c != '.') {
\r
249 double d = ScriptRuntime.stringToNumber(s, start, radix);
\r
250 return new Double(negative ? -d : d);
\r
254 * The global method parseFloat, as per ECMA-262 15.1.2.3.
\r
257 * @param thisObj unused
\r
258 * @param args the arguments to parseFloat, ignoring args[>=1]
\r
259 * @param funObj unused
\r
261 private Object js_parseFloat(Context cx, Object[] args) {
\r
262 if (args.length < 1)
\r
263 return ScriptRuntime.NaNobj;
\r
264 String s = ScriptRuntime.toString(args[0]);
\r
265 int len = s.length();
\r
267 return ScriptRuntime.NaNobj;
\r
271 // Scan forward to the first digit or .
\r
272 for (i=0; TokenStream.isJSSpace(c = s.charAt(i)) && i+1 < len; i++)
\r
278 if (c == '+' || c == '-')
\r
282 // check for "Infinity"
\r
284 if (i+8 <= len && s.substring(i, i+8).equals("Infinity"))
\r
285 d = s.charAt(start) == '-' ? Double.NEGATIVE_INFINITY
\r
286 : Double.POSITIVE_INFINITY;
\r
288 return ScriptRuntime.NaNobj;
\r
289 return new Double(d);
\r
292 // Find the end of the legal bit
\r
295 for (; i < len; i++) {
\r
296 switch (s.charAt(i)) {
\r
298 if (decimal != -1) // Only allow a single decimal point.
\r
305 if (exponent != -1)
\r
312 // Only allow '+' or '-' after 'e' or 'E'
\r
313 if (exponent != i-1)
\r
317 case '0': case '1': case '2': case '3': case '4':
\r
318 case '5': case '6': case '7': case '8': case '9':
\r
326 s = s.substring(start, i);
\r
328 return Double.valueOf(s);
\r
330 catch (NumberFormatException ex) {
\r
331 return ScriptRuntime.NaNobj;
\r
336 * The global method escape, as per ECMA-262 15.1.2.4.
\r
338 * Includes code for the 'mask' argument supported by the C escape
\r
339 * method, which used to be part of the browser imbedding. Blame
\r
340 * for the strange constant names should be directed there.
\r
343 private Object js_escape(Context cx, Object[] args) {
\r
349 String s = ScriptRuntime.toString(args, 0);
\r
351 int mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;
\r
352 if (args.length > 1) { // the 'mask' argument. Non-ECMA.
\r
353 double d = ScriptRuntime.toNumber(args[1]);
\r
354 if (d != d || ((mask = (int) d) != d) ||
\r
355 0 != (mask & ~(URL_XALPHAS | URL_XPALPHAS | URL_PATH)))
\r
357 String message = Context.getMessage0("msg.bad.esc.mask");
\r
358 cx.reportError(message);
\r
359 // do the ecma thing, in case reportError returns.
\r
360 mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;
\r
364 StringBuffer R = new StringBuffer();
\r
365 for (int k = 0; k < s.length(); k++) {
\r
366 int c = s.charAt(k), d;
\r
367 if (mask != 0 && ((c >= '0' && c <= '9') ||
\r
368 (c >= 'A' && c <= 'Z') ||
\r
369 (c >= 'a' && c <= 'z') ||
\r
370 c == '@' || c == '*' || c == '_' ||
\r
371 c == '-' || c == '.' ||
\r
372 ((c == '/' || c == '+') && mask > 3)))
\r
374 else if (c < 256) {
\r
375 if (c == ' ' && mask == URL_XPALPHAS) {
\r
379 R.append(hex_digit_to_char(c >>> 4));
\r
380 R.append(hex_digit_to_char(c & 0xF));
\r
385 R.append(hex_digit_to_char(c >>> 12));
\r
386 R.append(hex_digit_to_char((c & 0xF00) >>> 8));
\r
387 R.append(hex_digit_to_char((c & 0xF0) >>> 4));
\r
388 R.append(hex_digit_to_char(c & 0xF));
\r
391 return R.toString();
\r
394 private static char hex_digit_to_char(int x) {
\r
395 return (char)(x <= 9 ? x + '0' : x + ('A' - 10));
\r
399 * The global unescape method, as per ECMA-262 15.1.2.5.
\r
402 private Object js_unescape(Context cx, Object[] args)
\r
404 String s = ScriptRuntime.toString(args, 0);
\r
405 int firstEscapePos = s.indexOf('%');
\r
406 if (firstEscapePos >= 0) {
\r
407 int L = s.length();
\r
408 char[] buf = s.toCharArray();
\r
409 int destination = firstEscapePos;
\r
410 for (int k = firstEscapePos; k != L;) {
\r
413 if (c == '%' && k != L) {
\r
415 if (buf[k] == 'u') {
\r
424 for (int i = start; i != end; ++i) {
\r
425 x = (x << 4) | TokenStream.xDigitToInt(buf[i]);
\r
433 buf[destination] = c;
\r
436 s = new String(buf, 0, destination);
\r
442 * The global method isNaN, as per ECMA-262 15.1.2.6.
\r
445 private Object js_isNaN(Context cx, Object[] args) {
\r
446 if (args.length < 1)
\r
447 return Boolean.TRUE;
\r
448 double d = ScriptRuntime.toNumber(args[0]);
\r
449 return (d != d) ? Boolean.TRUE : Boolean.FALSE;
\r
452 private Object js_isFinite(Context cx, Object[] args) {
\r
453 if (args.length < 1)
\r
454 return Boolean.FALSE;
\r
455 double d = ScriptRuntime.toNumber(args[0]);
\r
456 return (d != d || d == Double.POSITIVE_INFINITY ||
\r
457 d == Double.NEGATIVE_INFINITY)
\r
462 private Object js_eval(Context cx, Scriptable scope, Object[] args)
\r
463 throws JavaScriptException
\r
465 String m = ScriptRuntime.getMessage1("msg.cant.call.indirect", "eval");
\r
466 throw NativeGlobal.constructError(cx, "EvalError", m, scope);
\r
470 * The eval function property of the global object.
\r
472 * See ECMA 15.1.2.1
\r
474 public static Object evalSpecial(Context cx, Scriptable scope,
\r
475 Object thisArg, Object[] args,
\r
476 String filename, int lineNumber)
\r
477 throws JavaScriptException
\r
479 throw NativeGlobal.constructError(cx, "EvalError", "XWT does not allow eval()", scope);
\r
481 if (args.length < 1)
\r
482 return Undefined.instance;
\r
483 Object x = args[0];
\r
484 if (!(x instanceof String)) {
\r
485 String message = Context.getMessage0("msg.eval.nonstring");
\r
486 Context.reportWarning(message);
\r
489 int[] linep = { lineNumber };
\r
490 if (filename == null) {
\r
491 filename = Context.getSourcePositionFromStack(linep);
\r
492 if (filename == null) {
\r
497 filename += "(eval)";
\r
500 StringReader in = new StringReader((String) x);
\r
501 Object securityDomain = cx.getSecurityDomainForStackDepth(3);
\r
503 // Compile the reader with opt level of -1 to force interpreter
\r
505 int oldOptLevel = cx.getOptimizationLevel();
\r
506 cx.setOptimizationLevel(-1);
\r
507 Script script = cx.compileReader(scope, in, filename, linep[0],
\r
509 cx.setOptimizationLevel(oldOptLevel);
\r
511 // if the compile fails, an error has been reported by the
\r
512 // compiler, but we need to stop execution to avoid
\r
513 // infinite looping on while(true) { eval('foo bar') } -
\r
514 // so we throw an EvaluatorException.
\r
515 if (script == null) {
\r
516 String message = Context.getMessage0("msg.syntax");
\r
517 throw new EvaluatorException(message);
\r
520 InterpretedScript is = (InterpretedScript) script;
\r
521 is.itsData.itsFromEvalCode = true;
\r
522 Object result = is.call(cx, scope, (Scriptable) thisArg, null);
\r
526 catch (IOException ioe) {
\r
527 // should never happen since we just made the Reader from a String
\r
528 throw new RuntimeException("unexpected io exception");
\r
535 * The NativeError functions
\r
539 public static EcmaError constructError(Context cx,
\r
544 int[] linep = { 0 };
\r
545 String filename = cx.getSourcePositionFromStack(linep);
\r
546 return constructError(cx, error, message, scope,
\r
547 filename, linep[0], 0, null);
\r
550 static EcmaError typeError0(String messageId, Object scope) {
\r
551 return constructError(Context.getContext(), "TypeError",
\r
552 ScriptRuntime.getMessage0(messageId), scope);
\r
555 static EcmaError typeError1(String messageId, Object arg1, Object scope) {
\r
556 return constructError(Context.getContext(), "TypeError",
\r
557 ScriptRuntime.getMessage1(messageId, arg1), scope);
\r
561 * The NativeError functions
\r
565 public static EcmaError constructError(Context cx,
\r
574 Scriptable scopeObject;
\r
576 scopeObject = (Scriptable) scope;
\r
578 catch (ClassCastException x) {
\r
579 throw new RuntimeException(x.toString());
\r
582 Object args[] = { message };
\r
584 Object errorObject = cx.newObject(scopeObject, error, args);
\r
585 return new EcmaError((NativeError)errorObject, sourceName,
\r
586 lineNumber, columnNumber, lineSource);
\r
588 catch (PropertyException x) {
\r
589 throw new RuntimeException(x.toString());
\r
591 catch (JavaScriptException x) {
\r
592 throw new RuntimeException(x.toString());
\r
594 catch (NotAFunctionException x) {
\r
595 throw new RuntimeException(x.toString());
\r
600 * The implementation of all the ECMA error constructors (SyntaxError,
\r
603 private Object new_CommonError(IdFunction ctorObj, Context cx,
\r
604 Scriptable scope, Object[] args)
\r
606 Scriptable newInstance = new NativeError();
\r
607 newInstance.setPrototype((Scriptable)(ctorObj.get("prototype", ctorObj)));
\r
608 newInstance.setParentScope(scope);
\r
609 if (args.length > 0)
\r
610 newInstance.put("message", newInstance, args[0]);
\r
611 return newInstance;
\r
615 * ECMA 3, 15.1.3 URI Handling Function Properties
\r
617 * The following are implementations of the algorithms
\r
618 * given in the ECMA specification for the hidden functions
\r
619 * 'Encode' and 'Decode'.
\r
621 private static String encode(Context cx, String str, String unescapedSet) {
\r
625 char utf8buf[] = new char[6];
\r
628 R = new StringBuffer();
\r
630 while (k < str.length()) {
\r
632 if (unescapedSet.indexOf(C) != -1) {
\r
635 if ((C >= 0xDC00) && (C <= 0xDFFF)) {
\r
636 throw cx.reportRuntimeError0("msg.bad.uri");
\r
638 if ((C < 0xD800) || (C > 0xDBFF))
\r
642 if (k == str.length()) {
\r
643 throw cx.reportRuntimeError0("msg.bad.uri");
\r
645 C2 = str.charAt(k);
\r
646 if ((C2 < 0xDC00) || (C2 > 0xDFFF)) {
\r
647 throw cx.reportRuntimeError0("msg.bad.uri");
\r
649 V = ((C - 0xD800) << 10) + (C2 - 0xDC00) + 0x10000;
\r
651 L = oneUcs4ToUtf8Char(utf8buf, V);
\r
652 for (j = 0; j < L; j++) {
\r
654 if (utf8buf[j] < 16)
\r
656 R.append(Integer.toHexString(utf8buf[j]));
\r
661 return R.toString();
\r
664 private static boolean isHex(char c) {
\r
665 return ((c >= '0' && c <= '9')
\r
666 || (c >= 'a' && c <= 'f')
\r
667 || (c >= 'A' && c <= 'F'));
\r
670 private static int unHex(char c) {
\r
671 if (c >= '0' && c <= '9')
\r
674 if (c >= 'a' && c <= 'f')
\r
675 return c - 'a' + 10;
\r
677 return c - 'A' +10;
\r
680 private static String decode(Context cx, String str, String reservedSet) {
\r
685 char[] octets = new char[6];
\r
689 R = new StringBuffer();
\r
691 while (k < str.length()) {
\r
695 if ((k + 2) >= str.length())
\r
696 throw cx.reportRuntimeError0("msg.bad.uri");
\r
697 if (!isHex(str.charAt(k + 1)) || !isHex(str.charAt(k + 2)))
\r
698 throw cx.reportRuntimeError0("msg.bad.uri");
\r
699 B = unHex(str.charAt(k + 1)) * 16 + unHex(str.charAt(k + 2));
\r
701 if ((B & 0x80) == 0)
\r
705 while ((B & (0x80 >>> n)) != 0) n++;
\r
706 if ((n == 1) || (n > 6))
\r
707 throw cx.reportRuntimeError0("msg.bad.uri");
\r
708 octets[0] = (char)B;
\r
709 if ((k + 3 * (n - 1)) >= str.length())
\r
710 throw cx.reportRuntimeError0("msg.bad.uri");
\r
711 for (j = 1; j < n; j++) {
\r
713 if (str.charAt(k) != '%')
\r
714 throw cx.reportRuntimeError0("msg.bad.uri");
\r
715 if (!isHex(str.charAt(k + 1))
\r
716 || !isHex(str.charAt(k + 2)))
\r
717 throw cx.reportRuntimeError0("msg.bad.uri");
\r
718 B = unHex(str.charAt(k + 1)) * 16
\r
719 + unHex(str.charAt(k + 2));
\r
720 if ((B & 0xC0) != 0x80)
\r
721 throw cx.reportRuntimeError0("msg.bad.uri");
\r
723 octets[j] = (char)B;
\r
725 V = utf8ToOneUcs4Char(octets, n);
\r
726 if (V >= 0x10000) {
\r
729 throw cx.reportRuntimeError0("msg.bad.uri");
\r
730 C = (char)((V & 0x3FF) + 0xDC00);
\r
731 H = (char)((V >>> 10) + 0xD800);
\r
737 if (reservedSet.indexOf(C) != -1) {
\r
738 for (int x = 0; x < (k - start + 1); x++)
\r
739 R.append(str.charAt(start + x));
\r
748 return R.toString();
\r
751 private static String uriReservedPlusPound = ";/?:@&=+$,#";
\r
752 private static String uriUnescaped =
\r
753 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.!~*'()";
\r
755 private String js_decodeURI(Context cx, Object[] args) {
\r
756 String str = ScriptRuntime.toString(args, 0);
\r
757 return decode(cx, str, uriReservedPlusPound);
\r
760 private String js_decodeURIComponent(Context cx, Object[] args) {
\r
761 String str = ScriptRuntime.toString(args, 0);
\r
762 return decode(cx, str, "");
\r
765 private Object js_encodeURI(Context cx, Object[] args) {
\r
766 String str = ScriptRuntime.toString(args, 0);
\r
767 return encode(cx, str, uriReservedPlusPound + uriUnescaped);
\r
770 private String js_encodeURIComponent(Context cx, Object[] args) {
\r
771 String str = ScriptRuntime.toString(args, 0);
\r
772 return encode(cx, str, uriUnescaped);
\r
775 /* Convert one UCS-4 char and write it into a UTF-8 buffer, which must be
\r
776 * at least 6 bytes long. Return the number of UTF-8 bytes of data written.
\r
778 private static int oneUcs4ToUtf8Char(char[] utf8Buffer, int ucs4Char) {
\r
779 int utf8Length = 1;
\r
781 //JS_ASSERT(ucs4Char <= 0x7FFFFFFF);
\r
782 if ((ucs4Char & ~0x7F) == 0)
\r
783 utf8Buffer[0] = (char)ucs4Char;
\r
786 int a = ucs4Char >>> 11;
\r
794 utf8Buffer[i] = (char)((ucs4Char & 0x3F) | 0x80);
\r
797 utf8Buffer[0] = (char)(0x100 - (1 << (8-utf8Length)) + ucs4Char);
\r
803 /* Convert a utf8 character sequence into a UCS-4 character and return that
\r
804 * character. It is assumed that the caller already checked that the sequence is valid.
\r
806 private static int utf8ToOneUcs4Char(char[] utf8Buffer, int utf8Length) {
\r
809 //JS_ASSERT(utf8Length >= 1 && utf8Length <= 6);
\r
810 if (utf8Length == 1) {
\r
811 ucs4Char = utf8Buffer[0];
\r
812 // JS_ASSERT(!(ucs4Char & 0x80));
\r
814 //JS_ASSERT((*utf8Buffer & (0x100 - (1 << (7-utf8Length)))) == (0x100 - (1 << (8-utf8Length))));
\r
815 ucs4Char = utf8Buffer[k++] & ((1<<(7-utf8Length))-1);
\r
816 while (--utf8Length > 0) {
\r
817 //JS_ASSERT((*utf8Buffer & 0xC0) == 0x80);
\r
818 ucs4Char = ucs4Char<<6 | (utf8Buffer[k++] & 0x3F);
\r
824 private static final int
\r
826 Id_decodeURIComponent = 2,
\r
828 Id_encodeURIComponent = 4,
\r
837 LAST_SCOPE_FUNCTION_ID = 11,
\r
839 Id_new_CommonError = 12;
\r
841 private boolean scopeSlaveFlag;
\r