/src/moddable/xs/sources/xsArguments.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2016-2017 Moddable Tech, Inc. |
3 | | * |
4 | | * This file is part of the Moddable SDK Runtime. |
5 | | * |
6 | | * The Moddable SDK Runtime is free software: you can redistribute it and/or modify |
7 | | * it under the terms of the GNU Lesser General Public License as published by |
8 | | * the Free Software Foundation, either version 3 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * The Moddable SDK Runtime is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public License |
17 | | * along with the Moddable SDK Runtime. If not, see <http://www.gnu.org/licenses/>. |
18 | | * |
19 | | * This file incorporates work covered by the following copyright and |
20 | | * permission notice: |
21 | | * |
22 | | * Copyright (C) 2010-2016 Marvell International Ltd. |
23 | | * Copyright (C) 2002-2010 Kinoma, Inc. |
24 | | * |
25 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
26 | | * you may not use this file except in compliance with the License. |
27 | | * You may obtain a copy of the License at |
28 | | * |
29 | | * http://www.apache.org/licenses/LICENSE-2.0 |
30 | | * |
31 | | * Unless required by applicable law or agreed to in writing, software |
32 | | * distributed under the License is distributed on an "AS IS" BASIS, |
33 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
34 | | * See the License for the specific language governing permissions and |
35 | | * limitations under the License. |
36 | | */ |
37 | | |
38 | | #include "xsAll.h" |
39 | | |
40 | | static txBoolean fxArgumentsSloppyDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* descriptor, txFlag mask); |
41 | | static txBoolean fxArgumentsSloppyDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index); |
42 | | static txSlot* fxArgumentsSloppyGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag); |
43 | | static txSlot* fxArgumentsSloppySetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag); |
44 | | |
45 | | const txBehavior ICACHE_FLASH_ATTR gxArgumentsSloppyBehavior = { |
46 | | fxArgumentsSloppyGetProperty, |
47 | | fxArgumentsSloppySetProperty, |
48 | | fxOrdinaryCall, |
49 | | fxOrdinaryConstruct, |
50 | | fxArgumentsSloppyDefineOwnProperty, |
51 | | fxArgumentsSloppyDeleteProperty, |
52 | | fxOrdinaryGetOwnProperty, |
53 | | fxOrdinaryGetPropertyValue, |
54 | | fxOrdinaryGetPrototype, |
55 | | fxOrdinaryHasProperty, |
56 | | fxOrdinaryIsExtensible, |
57 | | fxOrdinaryOwnKeys, |
58 | | fxOrdinaryPreventExtensions, |
59 | | fxOrdinarySetPropertyValue, |
60 | | fxOrdinarySetPrototype, |
61 | | }; |
62 | | |
63 | | void fxBuildArguments(txMachine* the) |
64 | 6.57k | { |
65 | 6.57k | mxPush(mxObjectPrototype); |
66 | 6.57k | mxArgumentsSloppyPrototype = *the->stack; |
67 | 6.57k | mxPop(); |
68 | | |
69 | 6.57k | mxPush(mxObjectPrototype); |
70 | 6.57k | mxArgumentsStrictPrototype = *the->stack; |
71 | 6.57k | mxPop(); |
72 | 6.57k | } |
73 | | |
74 | | txSlot* fxNewArgumentsSloppyInstance(txMachine* the, txIndex count) |
75 | 0 | { |
76 | 0 | txSlot* environment = mxFrameToEnvironment(the->frame); |
77 | 0 | txSlot* instance; |
78 | 0 | txSlot* array; |
79 | 0 | txSlot* property; |
80 | 0 | txIndex index; |
81 | 0 | txSlot* address; |
82 | 0 | txIndex length = (txIndex)mxArgc; |
83 | 0 | instance = fxNewObjectInstance(the); |
84 | 0 | instance->flag |= XS_EXOTIC_FLAG; |
85 | 0 | array = instance->next = fxNewSlot(the); |
86 | 0 | array->flag = XS_INTERNAL_FLAG; |
87 | 0 | array->ID = XS_ARGUMENTS_SLOPPY_BEHAVIOR; |
88 | 0 | array->kind = XS_ARRAY_KIND; |
89 | 0 | array->value.array.length = 0; |
90 | 0 | array->value.array.address = C_NULL; |
91 | 0 | property = fxNextNumberProperty(the, array, length, mxID(_length), XS_DONT_ENUM_FLAG); |
92 | 0 | property = fxNextSlotProperty(the, property, mxFunction, mxID(_callee), XS_DONT_ENUM_FLAG); |
93 | 0 | property = fxNextSlotProperty(the, property, &mxArrayIteratorFunction, mxID(_Symbol_iterator), XS_DONT_ENUM_FLAG); |
94 | 0 | fxSetIndexSize(the, array, length, XS_CHUNK); |
95 | 0 | index = 0; |
96 | 0 | address = array->value.array.address; |
97 | 0 | property = the->scope + count; |
98 | 0 | while ((index < length) && (index < count)) { |
99 | 0 | *((txIndex*)address) = index; |
100 | 0 | address->ID = XS_NO_ID; |
101 | 0 | if ((property < environment) && (property->kind == XS_CLOSURE_KIND)) { |
102 | 0 | address->kind = property->kind; |
103 | 0 | address->value = property->value; |
104 | 0 | } |
105 | 0 | else { |
106 | 0 | txSlot* argument = mxArgv(index); |
107 | 0 | address->kind = argument->kind; |
108 | 0 | address->value = argument->value; |
109 | 0 | } |
110 | 0 | index++; |
111 | 0 | address++; |
112 | 0 | property--; |
113 | 0 | } |
114 | 0 | while (index < length) { |
115 | 0 | property = mxArgv(index); |
116 | 0 | *((txIndex*)address) = index; |
117 | 0 | address->ID = XS_NO_ID; |
118 | 0 | address->kind = property->kind; |
119 | 0 | address->value = property->value; |
120 | 0 | index++; |
121 | 0 | address++; |
122 | 0 | } |
123 | 0 | return instance; |
124 | 0 | } |
125 | | |
126 | | txBoolean fxArgumentsSloppyDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* descriptor, txFlag mask) |
127 | 0 | { |
128 | 0 | if (!id) { |
129 | 0 | txSlot* property = fxGetIndexProperty(the, instance->next, index); |
130 | 0 | if (property && (property->kind == XS_CLOSURE_KIND)) { |
131 | 0 | txSlot* closure = property->value.closure; |
132 | 0 | if (mask & XS_ACCESSOR_FLAG) { |
133 | 0 | property->flag = closure->flag; |
134 | 0 | property->kind = closure->kind; |
135 | 0 | property->value = closure->value; |
136 | 0 | } |
137 | 0 | else if ((descriptor->flag & XS_DONT_SET_FLAG) && (mask & XS_DONT_SET_FLAG)) { |
138 | 0 | property->flag = closure->flag; |
139 | 0 | property->kind = closure->kind; |
140 | 0 | property->value = closure->value; |
141 | 0 | if (descriptor->kind != XS_UNINITIALIZED_KIND) { |
142 | 0 | closure->kind = descriptor->kind; |
143 | 0 | closure->value = descriptor->value; |
144 | 0 | } |
145 | 0 | } |
146 | 0 | } |
147 | 0 | } |
148 | 0 | return fxOrdinaryDefineOwnProperty(the, instance, id, index, descriptor, mask); |
149 | 0 | } |
150 | | |
151 | | txBoolean fxArgumentsSloppyDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index) |
152 | 0 | { |
153 | 0 | if (!id) { |
154 | 0 | txSlot* property = fxGetIndexProperty(the, instance->next, index); |
155 | 0 | if (property && (property->kind == XS_CLOSURE_KIND)) { |
156 | 0 | if (property->value.closure->flag & XS_DONT_DELETE_FLAG) |
157 | 0 | return 0; |
158 | 0 | } |
159 | 0 | } |
160 | 0 | return fxOrdinaryDeleteProperty(the, instance, id, index); |
161 | 0 | } |
162 | | |
163 | | txSlot* fxArgumentsSloppyGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag) |
164 | 0 | { |
165 | 0 | txSlot* result = fxOrdinaryGetProperty(the, instance, id, index, flag); |
166 | 0 | if (!id && result && result->kind == XS_CLOSURE_KIND) |
167 | 0 | result = result->value.closure; |
168 | 0 | return result; |
169 | 0 | } |
170 | | |
171 | | txSlot* fxArgumentsSloppySetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag) |
172 | 0 | { |
173 | 0 | txSlot* result = fxOrdinarySetProperty(the, instance, id, index, flag); |
174 | 0 | if (!id && result && result->kind == XS_CLOSURE_KIND) |
175 | 0 | result = result->value.closure; |
176 | 0 | return result; |
177 | 0 | } |
178 | | |
179 | | txSlot* fxNewArgumentsStrictInstance(txMachine* the, txIndex count) |
180 | 0 | { |
181 | 0 | txSlot* instance; |
182 | 0 | txSlot* array; |
183 | 0 | txSlot* property; |
184 | 0 | txSlot* function; |
185 | 0 | txIndex index; |
186 | 0 | txSlot* address; |
187 | 0 | txIndex length = (txIndex)mxArgc; |
188 | 0 | instance = fxNewObjectInstance(the); |
189 | 0 | instance->flag |= XS_EXOTIC_FLAG; |
190 | 0 | array = instance->next = fxNewSlot(the); |
191 | 0 | array->flag = XS_INTERNAL_FLAG; |
192 | 0 | array->ID = XS_ARGUMENTS_STRICT_BEHAVIOR; |
193 | 0 | array->kind = XS_ARRAY_KIND; |
194 | 0 | array->value.array.length = 0; |
195 | 0 | array->value.array.address = C_NULL; |
196 | 0 | property = fxNextNumberProperty(the, array, length, mxID(_length), XS_DONT_ENUM_FLAG); |
197 | 0 | property = fxNextSlotProperty(the, property, &mxArrayIteratorFunction, mxID(_Symbol_iterator), XS_DONT_ENUM_FLAG); |
198 | 0 | function = mxThrowTypeErrorFunction.value.reference; |
199 | 0 | property = property->next = fxNewSlot(the); |
200 | 0 | property->flag = XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG; |
201 | 0 | property->ID = mxID(_callee); |
202 | 0 | property->kind = XS_ACCESSOR_KIND; |
203 | 0 | property->value.accessor.getter = function; |
204 | 0 | property->value.accessor.setter = function; |
205 | 0 | fxSetIndexSize(the, array, length, XS_CHUNK); |
206 | 0 | index = 0; |
207 | 0 | address = array->value.array.address; |
208 | 0 | while (index < length) { |
209 | 0 | property = mxArgv(index); |
210 | 0 | *((txIndex*)address) = index; |
211 | 0 | address->ID = XS_NO_ID; |
212 | 0 | address->kind = property->kind; |
213 | 0 | address->value = property->value; |
214 | 0 | index++; |
215 | 0 | address++; |
216 | 0 | } |
217 | 0 | return instance; |
218 | 0 | } |
219 | | |
220 | | void fxThrowTypeError(txMachine* the) |
221 | 0 | { |
222 | 0 | if (mxFunction->value.reference->flag & XS_CAN_CONSTRUCT_FLAG) |
223 | 0 | mxTypeError("secure mode"); |
224 | 0 | mxTypeError("strict mode"); |
225 | 0 | } |