Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(241)

Side by Side Diff: src/object-observe.js

Issue 265503002: Re-enable Object.observe and add enforcement for security invariants. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: cr comment Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/messages.js ('k') | src/objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 "use strict"; 5 "use strict";
6 6
7 // Overview: 7 // Overview:
8 // 8 //
9 // This file contains all of the routing and accounting for Object.observe. 9 // This file contains all of the routing and accounting for Object.observe.
10 // User code will interact with these mechanisms via the Object.observe APIs 10 // User code will interact with these mechanisms via the Object.observe APIs
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 callbackInfo = new InternalArray; 348 callbackInfo = new InternalArray;
349 callbackInfo.priority = priority; 349 callbackInfo.priority = priority;
350 GetCallbackInfoMap().set(callback, callbackInfo); 350 GetCallbackInfoMap().set(callback, callbackInfo);
351 } 351 }
352 return callbackInfo; 352 return callbackInfo;
353 } 353 }
354 354
355 function ObjectObserve(object, callback, acceptList) { 355 function ObjectObserve(object, callback, acceptList) {
356 if (!IS_SPEC_OBJECT(object)) 356 if (!IS_SPEC_OBJECT(object))
357 throw MakeTypeError("observe_non_object", ["observe"]); 357 throw MakeTypeError("observe_non_object", ["observe"]);
358 if (%IsJSGlobalProxy(object))
359 throw MakeTypeError("observe_global_proxy", ["observe"]);
358 if (!IS_SPEC_FUNCTION(callback)) 360 if (!IS_SPEC_FUNCTION(callback))
359 throw MakeTypeError("observe_non_function", ["observe"]); 361 throw MakeTypeError("observe_non_function", ["observe"]);
360 if (ObjectIsFrozen(callback)) 362 if (ObjectIsFrozen(callback))
361 throw MakeTypeError("observe_callback_frozen"); 363 throw MakeTypeError("observe_callback_frozen");
362 if (!AcceptArgIsValid(acceptList)) 364 if (!AcceptArgIsValid(acceptList))
363 throw MakeTypeError("observe_accept_invalid"); 365 throw MakeTypeError("observe_accept_invalid");
364 366
365 var objectInfo = ObjectInfoGetOrCreate(object); 367 var objectInfo = ObjectInfoGetOrCreate(object);
366 ObjectInfoAddObserver(objectInfo, callback, acceptList); 368 ObjectInfoAddObserver(objectInfo, callback, acceptList);
367 return object; 369 return object;
368 } 370 }
369 371
370 function ObjectUnobserve(object, callback) { 372 function ObjectUnobserve(object, callback) {
371 if (!IS_SPEC_OBJECT(object)) 373 if (!IS_SPEC_OBJECT(object))
372 throw MakeTypeError("observe_non_object", ["unobserve"]); 374 throw MakeTypeError("observe_non_object", ["unobserve"]);
375 if (%IsJSGlobalProxy(object))
376 throw MakeTypeError("observe_global_proxy", ["unobserve"]);
373 if (!IS_SPEC_FUNCTION(callback)) 377 if (!IS_SPEC_FUNCTION(callback))
374 throw MakeTypeError("observe_non_function", ["unobserve"]); 378 throw MakeTypeError("observe_non_function", ["unobserve"]);
375 379
376 var objectInfo = ObjectInfoGet(object); 380 var objectInfo = ObjectInfoGet(object);
377 if (IS_UNDEFINED(objectInfo)) 381 if (IS_UNDEFINED(objectInfo))
378 return object; 382 return object;
379 383
380 ObjectInfoRemoveObserver(objectInfo, callback); 384 ObjectInfoRemoveObserver(objectInfo, callback);
381 return object; 385 return object;
382 } 386 }
383 387
384 function ArrayObserve(object, callback) { 388 function ArrayObserve(object, callback) {
385 return ObjectObserve(object, callback, ['add', 389 return ObjectObserve(object, callback, ['add',
386 'update', 390 'update',
387 'delete', 391 'delete',
388 'splice']); 392 'splice']);
389 } 393 }
390 394
391 function ArrayUnobserve(object, callback) { 395 function ArrayUnobserve(object, callback) {
392 return ObjectUnobserve(object, callback); 396 return ObjectUnobserve(object, callback);
393 } 397 }
394 398
395 function ObserverEnqueueIfActive(observer, objectInfo, changeRecord, 399 function ObserverEnqueueIfActive(observer, objectInfo, changeRecord) {
396 needsAccessCheck) {
397 if (!ObserverIsActive(observer, objectInfo) || 400 if (!ObserverIsActive(observer, objectInfo) ||
398 !TypeMapHasType(ObserverGetAcceptTypes(observer), changeRecord.type)) { 401 !TypeMapHasType(ObserverGetAcceptTypes(observer), changeRecord.type)) {
399 return; 402 return;
400 } 403 }
401 404
402 var callback = ObserverGetCallback(observer); 405 var callback = ObserverGetCallback(observer);
403 if (needsAccessCheck && 406 if (!%ObserverObjectAndRecordHaveSameOrigin(callback, changeRecord.object,
404 // Drop all splice records on the floor for access-checked objects 407 changeRecord)) {
405 (changeRecord.type == 'splice' ||
406 !%IsAccessAllowedForObserver(
407 callback, changeRecord.object, changeRecord.name))) {
408 return; 408 return;
409 } 409 }
410 410
411 var callbackInfo = CallbackInfoNormalize(callback); 411 var callbackInfo = CallbackInfoNormalize(callback);
412 if (IS_NULL(GetPendingObservers())) { 412 if (IS_NULL(GetPendingObservers())) {
413 SetPendingObservers(nullProtoObject()) 413 SetPendingObservers(nullProtoObject())
414 EnqueueMicrotask(ObserveMicrotaskRunner); 414 EnqueueMicrotask(ObserveMicrotaskRunner);
415 } 415 }
416 GetPendingObservers()[callbackInfo.priority] = callback; 416 GetPendingObservers()[callbackInfo.priority] = callback;
417 callbackInfo.push(changeRecord); 417 callbackInfo.push(changeRecord);
418 } 418 }
419 419
420 function ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, type) { 420 function ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, type) {
421 if (!ObjectInfoHasActiveObservers(objectInfo)) 421 if (!ObjectInfoHasActiveObservers(objectInfo))
422 return; 422 return;
423 423
424 var hasType = !IS_UNDEFINED(type); 424 var hasType = !IS_UNDEFINED(type);
425 var newRecord = hasType ? 425 var newRecord = hasType ?
426 { object: ObjectInfoGetObject(objectInfo), type: type } : 426 { object: ObjectInfoGetObject(objectInfo), type: type } :
427 { object: ObjectInfoGetObject(objectInfo) }; 427 { object: ObjectInfoGetObject(objectInfo) };
428 428
429 for (var prop in changeRecord) { 429 for (var prop in changeRecord) {
430 if (prop === 'object' || (hasType && prop === 'type')) continue; 430 if (prop === 'object' || (hasType && prop === 'type')) continue;
431 %DefineOrRedefineDataProperty(newRecord, prop, changeRecord[prop], 431 %DefineOrRedefineDataProperty(newRecord, prop, changeRecord[prop],
432 READ_ONLY + DONT_DELETE); 432 READ_ONLY + DONT_DELETE);
433 } 433 }
434 ObjectFreeze(newRecord); 434 ObjectFreeze(newRecord);
435 435
436 ObjectInfoEnqueueInternalChangeRecord(objectInfo, newRecord, 436 ObjectInfoEnqueueInternalChangeRecord(objectInfo, newRecord);
437 true /* skip access check */);
438 } 437 }
439 438
440 function ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord, 439 function ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord) {
441 skipAccessCheck) {
442 // TODO(rossberg): adjust once there is a story for symbols vs proxies. 440 // TODO(rossberg): adjust once there is a story for symbols vs proxies.
443 if (IS_SYMBOL(changeRecord.name)) return; 441 if (IS_SYMBOL(changeRecord.name)) return;
444 442
445 var needsAccessCheck = !skipAccessCheck &&
446 %IsAccessCheckNeeded(changeRecord.object);
447
448 if (ChangeObserversIsOptimized(objectInfo.changeObservers)) { 443 if (ChangeObserversIsOptimized(objectInfo.changeObservers)) {
449 var observer = objectInfo.changeObservers; 444 var observer = objectInfo.changeObservers;
450 ObserverEnqueueIfActive(observer, objectInfo, changeRecord, 445 ObserverEnqueueIfActive(observer, objectInfo, changeRecord);
451 needsAccessCheck);
452 return; 446 return;
453 } 447 }
454 448
455 for (var priority in objectInfo.changeObservers) { 449 for (var priority in objectInfo.changeObservers) {
456 var observer = objectInfo.changeObservers[priority]; 450 var observer = objectInfo.changeObservers[priority];
457 if (IS_NULL(observer)) 451 if (IS_NULL(observer))
458 continue; 452 continue;
459 ObserverEnqueueIfActive(observer, objectInfo, changeRecord, 453 ObserverEnqueueIfActive(observer, objectInfo, changeRecord);
460 needsAccessCheck);
461 } 454 }
462 } 455 }
463 456
464 function BeginPerformSplice(array) { 457 function BeginPerformSplice(array) {
465 var objectInfo = ObjectInfoGet(array); 458 var objectInfo = ObjectInfoGet(array);
466 if (!IS_UNDEFINED(objectInfo)) 459 if (!IS_UNDEFINED(objectInfo))
467 ObjectInfoAddPerformingType(objectInfo, 'splice'); 460 ObjectInfoAddPerformingType(objectInfo, 'splice');
468 } 461 }
469 462
470 function EndPerformSplice(array) { 463 function EndPerformSplice(array) {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 ObjectInfoRemovePerformingType(objectInfo, changeType); 544 ObjectInfoRemovePerformingType(objectInfo, changeType);
552 } 545 }
553 546
554 if (IS_SPEC_OBJECT(changeRecord)) 547 if (IS_SPEC_OBJECT(changeRecord))
555 ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, changeType); 548 ObjectInfoEnqueueExternalChangeRecord(objectInfo, changeRecord, changeType);
556 } 549 }
557 550
558 function ObjectGetNotifier(object) { 551 function ObjectGetNotifier(object) {
559 if (!IS_SPEC_OBJECT(object)) 552 if (!IS_SPEC_OBJECT(object))
560 throw MakeTypeError("observe_non_object", ["getNotifier"]); 553 throw MakeTypeError("observe_non_object", ["getNotifier"]);
554 if (%IsJSGlobalProxy(object))
555 throw MakeTypeError("observe_global_proxy", ["getNotifier"]);
561 556
562 if (ObjectIsFrozen(object)) return null; 557 if (ObjectIsFrozen(object)) return null;
563 558
559 if (!%ObjectWasCreatedInCurrentOrigin(object)) return null;
560
564 var objectInfo = ObjectInfoGetOrCreate(object); 561 var objectInfo = ObjectInfoGetOrCreate(object);
565 return ObjectInfoGetNotifier(objectInfo); 562 return ObjectInfoGetNotifier(objectInfo);
566 } 563 }
567 564
568 function CallbackDeliverPending(callback) { 565 function CallbackDeliverPending(callback) {
569 var callbackInfo = GetCallbackInfoMap().get(callback); 566 var callbackInfo = GetCallbackInfoMap().get(callback);
570 if (IS_UNDEFINED(callbackInfo) || IS_NUMBER(callbackInfo)) 567 if (IS_UNDEFINED(callbackInfo) || IS_NUMBER(callbackInfo))
571 return false; 568 return false;
572 569
573 // Clear the pending change records from callback and return it to its 570 // Clear the pending change records from callback and return it to its
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 InstallFunctions($Array, DONT_ENUM, $Array( 612 InstallFunctions($Array, DONT_ENUM, $Array(
616 "observe", ArrayObserve, 613 "observe", ArrayObserve,
617 "unobserve", ArrayUnobserve 614 "unobserve", ArrayUnobserve
618 )); 615 ));
619 InstallFunctions(notifierPrototype, DONT_ENUM, $Array( 616 InstallFunctions(notifierPrototype, DONT_ENUM, $Array(
620 "notify", ObjectNotifierNotify, 617 "notify", ObjectNotifierNotify,
621 "performChange", ObjectNotifierPerformChange 618 "performChange", ObjectNotifierPerformChange
622 )); 619 ));
623 } 620 }
624 621
625 // Disable Object.observe API for M35. 622 SetupObjectObserve();
626 // SetupObjectObserve();
OLDNEW
« no previous file with comments | « src/messages.js ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698