Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
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/. */
7 #ifndef vm_Interpreter_h
8 #define vm_Interpreter_h
10 /*
11 * JS interpreter interface.
12 */
14 #include "jsiter.h"
15 #include "jspubtd.h"
17 #include "vm/Stack.h"
19 namespace js {
21 class ScopeIter;
23 /*
24 * Announce to the debugger that the thread has entered a new JavaScript frame,
25 * |frame|. Call whatever hooks have been registered to observe new frames, and
26 * return a JSTrapStatus code indication how execution should proceed:
27 *
28 * - JSTRAP_CONTINUE: Continue execution normally.
29 *
30 * - JSTRAP_THROW: Throw an exception. ScriptDebugPrologue has set |cx|'s
31 * pending exception to the value to be thrown.
32 *
33 * - JSTRAP_ERROR: Terminate execution (as is done when a script is terminated
34 * for running too long). ScriptDebugPrologue has cleared |cx|'s pending
35 * exception.
36 *
37 * - JSTRAP_RETURN: Return from the new frame immediately. ScriptDebugPrologue
38 * has set |frame|'s return value appropriately.
39 */
40 extern JSTrapStatus
41 ScriptDebugPrologue(JSContext *cx, AbstractFramePtr frame, jsbytecode *pc);
43 /*
44 * Announce to the debugger that the thread has exited a JavaScript frame, |frame|.
45 * If |ok| is true, the frame is returning normally; if |ok| is false, the frame
46 * is throwing an exception or terminating.
47 *
48 * Call whatever hooks have been registered to observe frame exits. Change cx's
49 * current exception and |frame|'s return value to reflect the changes in behavior
50 * the hooks request, if any. Return the new error/success value.
51 *
52 * This function may be called twice for the same outgoing frame; only the
53 * first call has any effect. (Permitting double calls simplifies some
54 * cases where an onPop handler's resumption value changes a return to a
55 * throw, or vice versa: we can redirect to a complete copy of the
56 * alternative path, containing its own call to ScriptDebugEpilogue.)
57 */
58 extern bool
59 ScriptDebugEpilogue(JSContext *cx, AbstractFramePtr frame, jsbytecode *pc, bool ok);
61 /*
62 * Announce to the debugger that an exception has been thrown and propagated
63 * to |frame|. Call whatever hooks have been registered to observe this and
64 * return a JSTrapStatus code indication how execution should proceed:
65 *
66 * - JSTRAP_CONTINUE: Continue throwing the current exception.
67 *
68 * - JSTRAP_THROW: Throw another value. DebugExceptionUnwind has set |cx|'s
69 * pending exception to the new value.
70 *
71 * - JSTRAP_ERROR: Terminate execution. DebugExceptionUnwind has cleared |cx|'s
72 * pending exception.
73 *
74 * - JSTRAP_RETURN: Return from |frame|. DebugExceptionUnwind has cleared
75 * |cx|'s pending exception and set |frame|'s return value.
76 */
77 extern JSTrapStatus
78 DebugExceptionUnwind(JSContext *cx, AbstractFramePtr frame, jsbytecode *pc);
80 /*
81 * For a given |call|, convert null/undefined |this| into the global object for
82 * the callee and replace other primitives with boxed versions. This assumes
83 * that call.callee() is not strict mode code. This is the special/slow case of
84 * ComputeThis.
85 */
86 extern bool
87 BoxNonStrictThis(JSContext *cx, const CallReceiver &call);
89 extern JSObject *
90 BoxNonStrictThis(JSContext *cx, HandleValue thisv);
92 /*
93 * Ensure that fp->thisValue() is the correct value of |this| for the scripted
94 * call represented by |fp|. ComputeThis is necessary because fp->thisValue()
95 * may be set to 'undefined' when 'this' should really be the global object (as
96 * an optimization to avoid global-this computation).
97 */
98 inline bool
99 ComputeThis(JSContext *cx, AbstractFramePtr frame);
101 enum MaybeConstruct {
102 NO_CONSTRUCT = INITIAL_NONE,
103 CONSTRUCT = INITIAL_CONSTRUCT
104 };
106 /*
107 * numToSkip is the number of stack values the expression decompiler should skip
108 * before it reaches |v|. If it's -1, the decompiler will search the stack.
109 */
110 extern bool
111 ReportIsNotFunction(JSContext *cx, HandleValue v, int numToSkip = -1,
112 MaybeConstruct construct = NO_CONSTRUCT);
114 /* See ReportIsNotFunction comment for the meaning of numToSkip. */
115 extern JSObject *
116 ValueToCallable(JSContext *cx, HandleValue v, int numToSkip = -1,
117 MaybeConstruct construct = NO_CONSTRUCT);
119 /*
120 * Invoke assumes that the given args have been pushed on the top of the
121 * VM stack.
122 */
123 extern bool
124 Invoke(JSContext *cx, CallArgs args, MaybeConstruct construct = NO_CONSTRUCT);
126 /*
127 * This Invoke overload places the least requirements on the caller: it may be
128 * called at any time and it takes care of copying the given callee, this, and
129 * arguments onto the stack.
130 */
131 extern bool
132 Invoke(JSContext *cx, const Value &thisv, const Value &fval, unsigned argc, const Value *argv,
133 MutableHandleValue rval);
135 /*
136 * This helper takes care of the infinite-recursion check necessary for
137 * getter/setter calls.
138 */
139 extern bool
140 InvokeGetterOrSetter(JSContext *cx, JSObject *obj, Value fval, unsigned argc, Value *argv,
141 MutableHandleValue rval);
143 /*
144 * InvokeConstructor implement a function call from a constructor context
145 * (e.g. 'new') handling the the creation of the new 'this' object.
146 */
147 extern bool
148 InvokeConstructor(JSContext *cx, CallArgs args);
150 /* See the fval overload of Invoke. */
151 extern bool
152 InvokeConstructor(JSContext *cx, Value fval, unsigned argc, Value *argv, Value *rval);
154 /*
155 * Executes a script with the given scopeChain/this. The 'type' indicates
156 * whether this is eval code or global code. To support debugging, the
157 * evalFrame parameter can point to an arbitrary frame in the context's call
158 * stack to simulate executing an eval in that frame.
159 */
160 extern bool
161 ExecuteKernel(JSContext *cx, HandleScript script, JSObject &scopeChain, const Value &thisv,
162 ExecuteType type, AbstractFramePtr evalInFrame, Value *result);
164 /* Execute a script with the given scopeChain as global code. */
165 extern bool
166 Execute(JSContext *cx, HandleScript script, JSObject &scopeChain, Value *rval);
168 class ExecuteState;
169 class InvokeState;
170 class GeneratorState;
172 // RunState is passed to RunScript and RunScript then eiter passes it to the
173 // interpreter or to the JITs. RunState contains all information we need to
174 // construct an interpreter or JIT frame.
175 class RunState
176 {
177 protected:
178 enum Kind { Execute, Invoke, Generator };
179 Kind kind_;
181 RootedScript script_;
183 explicit RunState(JSContext *cx, Kind kind, JSScript *script)
184 : kind_(kind),
185 script_(cx, script)
186 { }
188 public:
189 bool isExecute() const { return kind_ == Execute; }
190 bool isInvoke() const { return kind_ == Invoke; }
191 bool isGenerator() const { return kind_ == Generator; }
193 ExecuteState *asExecute() const {
194 JS_ASSERT(isExecute());
195 return (ExecuteState *)this;
196 }
197 InvokeState *asInvoke() const {
198 JS_ASSERT(isInvoke());
199 return (InvokeState *)this;
200 }
201 GeneratorState *asGenerator() const {
202 JS_ASSERT(isGenerator());
203 return (GeneratorState *)this;
204 }
206 JSScript *script() const { return script_; }
208 virtual InterpreterFrame *pushInterpreterFrame(JSContext *cx) = 0;
209 virtual void setReturnValue(Value v) = 0;
211 private:
212 RunState(const RunState &other) MOZ_DELETE;
213 RunState(const ExecuteState &other) MOZ_DELETE;
214 RunState(const InvokeState &other) MOZ_DELETE;
215 RunState(const GeneratorState &other) MOZ_DELETE;
216 void operator=(const RunState &other) MOZ_DELETE;
217 };
219 // Eval or global script.
220 class ExecuteState : public RunState
221 {
222 ExecuteType type_;
224 RootedValue thisv_;
225 RootedObject scopeChain_;
227 AbstractFramePtr evalInFrame_;
228 Value *result_;
230 public:
231 ExecuteState(JSContext *cx, JSScript *script, const Value &thisv, JSObject &scopeChain,
232 ExecuteType type, AbstractFramePtr evalInFrame, Value *result)
233 : RunState(cx, Execute, script),
234 type_(type),
235 thisv_(cx, thisv),
236 scopeChain_(cx, &scopeChain),
237 evalInFrame_(evalInFrame),
238 result_(result)
239 { }
241 Value *addressOfThisv() { return thisv_.address(); }
242 JSObject *scopeChain() const { return scopeChain_; }
243 ExecuteType type() const { return type_; }
245 virtual InterpreterFrame *pushInterpreterFrame(JSContext *cx);
247 virtual void setReturnValue(Value v) {
248 if (result_)
249 *result_ = v;
250 }
251 };
253 // Data to invoke a function.
254 class InvokeState : public RunState
255 {
256 CallArgs &args_;
257 InitialFrameFlags initial_;
258 bool useNewType_;
260 public:
261 InvokeState(JSContext *cx, CallArgs &args, InitialFrameFlags initial)
262 : RunState(cx, Invoke, args.callee().as<JSFunction>().nonLazyScript()),
263 args_(args),
264 initial_(initial),
265 useNewType_(false)
266 { }
268 bool useNewType() const { return useNewType_; }
269 void setUseNewType() { useNewType_ = true; }
271 bool constructing() const { return InitialFrameFlagsAreConstructing(initial_); }
272 CallArgs &args() const { return args_; }
274 virtual InterpreterFrame *pushInterpreterFrame(JSContext *cx);
276 virtual void setReturnValue(Value v) {
277 args_.rval().set(v);
278 }
279 };
281 // Generator script.
282 class GeneratorState : public RunState
283 {
284 JSContext *cx_;
285 JSGenerator *gen_;
286 JSGeneratorState futureState_;
287 bool entered_;
289 public:
290 GeneratorState(JSContext *cx, JSGenerator *gen, JSGeneratorState futureState);
291 ~GeneratorState();
293 virtual InterpreterFrame *pushInterpreterFrame(JSContext *cx);
294 virtual void setReturnValue(Value) { }
296 JSGenerator *gen() const { return gen_; }
297 };
299 extern bool
300 RunScript(JSContext *cx, RunState &state);
302 extern bool
303 StrictlyEqual(JSContext *cx, const Value &lval, const Value &rval, bool *equal);
305 extern bool
306 LooselyEqual(JSContext *cx, const Value &lval, const Value &rval, bool *equal);
308 /* === except that NaN is the same as NaN and -0 is not the same as +0. */
309 extern bool
310 SameValue(JSContext *cx, const Value &v1, const Value &v2, bool *same);
312 extern JSType
313 TypeOfObject(JSObject *obj);
315 extern JSType
316 TypeOfValue(const Value &v);
318 extern bool
319 HasInstance(JSContext *cx, HandleObject obj, HandleValue v, bool *bp);
321 // Unwind scope chain and iterator to match the static scope corresponding to
322 // the given bytecode position.
323 extern void
324 UnwindScope(JSContext *cx, ScopeIter &si, jsbytecode *pc);
326 /*
327 * Unwind for an uncatchable exception. This means not running finalizers, etc;
328 * just preserving the basic engine stack invariants.
329 */
330 extern void
331 UnwindForUncatchableException(JSContext *cx, const InterpreterRegs ®s);
333 extern bool
334 OnUnknownMethod(JSContext *cx, HandleObject obj, Value idval, MutableHandleValue vp);
336 class TryNoteIter
337 {
338 const InterpreterRegs ®s;
339 RootedScript script; /* TryNotIter is always stack allocated. */
340 uint32_t pcOffset;
341 JSTryNote *tn, *tnEnd;
343 void settle();
345 public:
346 explicit TryNoteIter(JSContext *cx, const InterpreterRegs ®s);
347 bool done() const;
348 void operator++();
349 JSTryNote *operator*() const { return tn; }
350 };
352 /************************************************************************/
354 bool
355 Throw(JSContext *cx, HandleValue v);
357 bool
358 GetProperty(JSContext *cx, HandleValue value, HandlePropertyName name, MutableHandleValue vp);
360 bool
361 CallProperty(JSContext *cx, HandleValue value, HandlePropertyName name, MutableHandleValue vp);
363 bool
364 GetScopeName(JSContext *cx, HandleObject obj, HandlePropertyName name, MutableHandleValue vp);
366 bool
367 GetScopeNameForTypeOf(JSContext *cx, HandleObject obj, HandlePropertyName name,
368 MutableHandleValue vp);
370 JSObject *
371 Lambda(JSContext *cx, HandleFunction fun, HandleObject parent);
373 JSObject *
374 LambdaArrow(JSContext *cx, HandleFunction fun, HandleObject parent, HandleValue thisv);
376 bool
377 GetElement(JSContext *cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res);
379 bool
380 CallElement(JSContext *cx, MutableHandleValue lref, HandleValue rref, MutableHandleValue res);
382 bool
383 SetObjectElement(JSContext *cx, HandleObject obj, HandleValue index, HandleValue value,
384 bool strict);
385 bool
386 SetObjectElement(JSContext *cx, HandleObject obj, HandleValue index, HandleValue value,
387 bool strict, HandleScript script, jsbytecode *pc);
389 bool
390 InitElementArray(JSContext *cx, jsbytecode *pc,
391 HandleObject obj, uint32_t index, HandleValue value);
393 bool
394 AddValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
396 bool
397 SubValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
399 bool
400 MulValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
402 bool
403 DivValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
405 bool
406 ModValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
408 bool
409 UrshValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res);
411 template <bool strict>
412 bool
413 SetProperty(JSContext *cx, HandleObject obj, HandleId id, const Value &value);
415 template <bool strict>
416 bool
417 DeleteProperty(JSContext *ctx, HandleValue val, HandlePropertyName name, bool *bv);
419 template <bool strict>
420 bool
421 DeleteElement(JSContext *cx, HandleValue val, HandleValue index, bool *bv);
423 bool
424 DefFunOperation(JSContext *cx, HandleScript script, HandleObject scopeChain, HandleFunction funArg);
426 bool
427 SetCallOperation(JSContext *cx);
429 bool
430 GetAndClearException(JSContext *cx, MutableHandleValue res);
432 bool
433 DeleteNameOperation(JSContext *cx, HandlePropertyName name, HandleObject scopeObj,
434 MutableHandleValue res);
436 bool
437 ImplicitThisOperation(JSContext *cx, HandleObject scopeObj, HandlePropertyName name,
438 MutableHandleValue res);
440 bool
441 IteratorMore(JSContext *cx, JSObject *iterobj, bool *cond, MutableHandleValue rval);
443 bool
444 IteratorNext(JSContext *cx, HandleObject iterobj, MutableHandleValue rval);
446 bool
447 RunOnceScriptPrologue(JSContext *cx, HandleScript script);
449 bool
450 InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, HandleId id,
451 HandleObject val);
453 bool
454 InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, HandlePropertyName name,
455 HandleObject val);
457 bool
458 EnterWithOperation(JSContext *cx, AbstractFramePtr frame, HandleValue val, HandleObject staticWith);
461 bool
462 InitGetterSetterOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, HandleValue idval,
463 HandleObject val);
465 inline bool
466 SetConstOperation(JSContext *cx, HandleObject varobj, HandlePropertyName name, HandleValue rval)
467 {
468 return JSObject::defineProperty(cx, varobj, name, rval,
469 JS_PropertyStub, JS_StrictPropertyStub,
470 JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY);
471 }
473 } /* namespace js */
475 #endif /* vm_Interpreter_h */