/src/moddable/xs/sources/xsArguments.c
Line | Count | Source |
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 | 27.4k | { |
65 | 27.4k | mxPush(mxObjectPrototype); |
66 | 27.4k | mxArgumentsSloppyPrototype = *the->stack; |
67 | 27.4k | mxPop(); |
68 | | |
69 | 27.4k | mxPush(mxObjectPrototype); |
70 | 27.4k | mxArgumentsStrictPrototype = *the->stack; |
71 | 27.4k | mxPop(); |
72 | 27.4k | } |
73 | | |
74 | | txSlot* fxNewArgumentsSloppyInstance(txMachine* the, txIndex count) |
75 | 144k | { |
76 | 144k | txSlot* environment = mxFrameToEnvironment(the->frame); |
77 | 144k | txSlot* instance; |
78 | 144k | txSlot* array; |
79 | 144k | txSlot* property; |
80 | 144k | txIndex index; |
81 | 144k | txSlot* address; |
82 | 144k | txIndex length = (txIndex)mxArgc; |
83 | 144k | instance = fxNewObjectInstance(the); |
84 | 144k | instance->flag |= XS_EXOTIC_FLAG; |
85 | 144k | array = instance->next = fxNewSlot(the); |
86 | 144k | array->flag = XS_INTERNAL_FLAG; |
87 | 144k | array->ID = XS_ARGUMENTS_SLOPPY_BEHAVIOR; |
88 | 144k | array->kind = XS_ARRAY_KIND; |
89 | 144k | array->value.array.length = 0; |
90 | 144k | array->value.array.address = C_NULL; |
91 | 144k | property = fxNextNumberProperty(the, array, length, mxID(_length), XS_DONT_ENUM_FLAG); |
92 | 144k | property = fxNextSlotProperty(the, property, mxFunction, mxID(_callee), XS_DONT_ENUM_FLAG); |
93 | 144k | property = fxNextSlotProperty(the, property, &mxArrayIteratorFunction, mxID(_Symbol_iterator), XS_DONT_ENUM_FLAG); |
94 | 144k | fxSetIndexSize(the, array, length, XS_CHUNK); |
95 | 144k | index = 0; |
96 | 144k | address = array->value.array.address; |
97 | 144k | property = the->scope + count; |
98 | 154k | while ((index < length) && (index < count)) { |
99 | 9.88k | *((txIndex*)address) = index; |
100 | 9.88k | address->ID = XS_NO_ID; |
101 | 9.88k | if ((property < environment) && (property->kind == XS_CLOSURE_KIND)) { |
102 | 8.25k | address->kind = property->kind; |
103 | 8.25k | address->value = property->value; |
104 | 8.25k | } |
105 | 1.63k | else { |
106 | 1.63k | txSlot* argument = mxArgv(index); |
107 | 1.63k | address->kind = argument->kind; |
108 | 1.63k | address->value = argument->value; |
109 | 1.63k | } |
110 | 9.88k | index++; |
111 | 9.88k | address++; |
112 | 9.88k | property--; |
113 | 9.88k | } |
114 | 145k | while (index < length) { |
115 | 180 | property = mxArgv(index); |
116 | 180 | *((txIndex*)address) = index; |
117 | 180 | address->ID = XS_NO_ID; |
118 | 180 | address->kind = property->kind; |
119 | 180 | address->value = property->value; |
120 | 180 | index++; |
121 | 180 | address++; |
122 | 180 | } |
123 | 144k | return instance; |
124 | 144k | } |
125 | | |
126 | | txBoolean fxArgumentsSloppyDefineOwnProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txSlot* descriptor, txFlag mask) |
127 | 168 | { |
128 | 168 | if (!id) { |
129 | 149 | txSlot* property = fxGetIndexProperty(the, instance->next, index); |
130 | 149 | if (property && (property->kind == XS_CLOSURE_KIND)) { |
131 | 96 | txSlot* closure = property->value.closure; |
132 | 96 | if (mask & XS_ACCESSOR_FLAG) { |
133 | 14 | property->flag = closure->flag; |
134 | 14 | property->kind = closure->kind; |
135 | 14 | property->value = closure->value; |
136 | 14 | } |
137 | 82 | else if ((descriptor->flag & XS_DONT_SET_FLAG) && (mask & XS_DONT_SET_FLAG)) { |
138 | 25 | property->flag = closure->flag; |
139 | 25 | property->kind = closure->kind; |
140 | 25 | property->value = closure->value; |
141 | 25 | if (descriptor->kind != XS_UNINITIALIZED_KIND) { |
142 | 6 | closure->kind = descriptor->kind; |
143 | 6 | closure->value = descriptor->value; |
144 | 6 | } |
145 | 25 | } |
146 | 96 | } |
147 | 149 | } |
148 | 168 | return fxOrdinaryDefineOwnProperty(the, instance, id, index, descriptor, mask); |
149 | 168 | } |
150 | | |
151 | | txBoolean fxArgumentsSloppyDeleteProperty(txMachine* the, txSlot* instance, txID id, txIndex index) |
152 | 8 | { |
153 | 8 | if (!id) { |
154 | 7 | txSlot* property = fxGetIndexProperty(the, instance->next, index); |
155 | 7 | if (property && (property->kind == XS_CLOSURE_KIND)) { |
156 | 3 | if (property->value.closure->flag & XS_DONT_DELETE_FLAG) |
157 | 0 | return 0; |
158 | 3 | } |
159 | 7 | } |
160 | 8 | return fxOrdinaryDeleteProperty(the, instance, id, index); |
161 | 8 | } |
162 | | |
163 | | txSlot* fxArgumentsSloppyGetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag) |
164 | 12.3k | { |
165 | 12.3k | txSlot* result = fxOrdinaryGetProperty(the, instance, id, index, flag); |
166 | 12.3k | if (!id && result && result->kind == XS_CLOSURE_KIND) |
167 | 202 | result = result->value.closure; |
168 | 12.3k | return result; |
169 | 12.3k | } |
170 | | |
171 | | txSlot* fxArgumentsSloppySetProperty(txMachine* the, txSlot* instance, txID id, txIndex index, txFlag flag) |
172 | 54 | { |
173 | 54 | txSlot* result = fxOrdinarySetProperty(the, instance, id, index, flag); |
174 | 54 | if (!id && result && result->kind == XS_CLOSURE_KIND) |
175 | 1 | result = result->value.closure; |
176 | 54 | return result; |
177 | 54 | } |
178 | | |
179 | | txSlot* fxNewArgumentsStrictInstance(txMachine* the, txIndex count) |
180 | 113k | { |
181 | 113k | txSlot* instance; |
182 | 113k | txSlot* array; |
183 | 113k | txSlot* property; |
184 | 113k | txSlot* function; |
185 | 113k | txIndex index; |
186 | 113k | txSlot* address; |
187 | 113k | txIndex length = (txIndex)mxArgc; |
188 | 113k | instance = fxNewObjectInstance(the); |
189 | 113k | instance->flag |= XS_EXOTIC_FLAG; |
190 | 113k | array = instance->next = fxNewSlot(the); |
191 | 113k | array->flag = XS_INTERNAL_FLAG; |
192 | 113k | array->ID = XS_ARGUMENTS_STRICT_BEHAVIOR; |
193 | 113k | array->kind = XS_ARRAY_KIND; |
194 | 113k | array->value.array.length = 0; |
195 | 113k | array->value.array.address = C_NULL; |
196 | 113k | property = fxNextNumberProperty(the, array, length, mxID(_length), XS_DONT_ENUM_FLAG); |
197 | 113k | property = fxNextSlotProperty(the, property, &mxArrayIteratorFunction, mxID(_Symbol_iterator), XS_DONT_ENUM_FLAG); |
198 | 113k | function = mxThrowTypeErrorFunction.value.reference; |
199 | 113k | property = property->next = fxNewSlot(the); |
200 | 113k | property->flag = XS_DONT_DELETE_FLAG | XS_DONT_ENUM_FLAG; |
201 | 113k | property->ID = mxID(_callee); |
202 | 113k | property->kind = XS_ACCESSOR_KIND; |
203 | 113k | property->value.accessor.getter = function; |
204 | 113k | property->value.accessor.setter = function; |
205 | 113k | fxSetIndexSize(the, array, length, XS_CHUNK); |
206 | 113k | index = 0; |
207 | 113k | address = array->value.array.address; |
208 | 198k | while (index < length) { |
209 | 84.8k | property = mxArgv(index); |
210 | 84.8k | *((txIndex*)address) = index; |
211 | 84.8k | address->ID = XS_NO_ID; |
212 | 84.8k | address->kind = property->kind; |
213 | 84.8k | address->value = property->value; |
214 | 84.8k | index++; |
215 | 84.8k | address++; |
216 | 84.8k | } |
217 | 113k | return instance; |
218 | 113k | } |
219 | | |
220 | | void fxThrowTypeError(txMachine* the) |
221 | 9 | { |
222 | 9 | if (mxFunction->value.reference->flag & XS_CAN_CONSTRUCT_FLAG) |
223 | 1 | mxTypeError("secure mode"); |
224 | 8 | mxTypeError("strict mode"); |
225 | 9 | } |